#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <pthread.h>
#include <string>


// 创造线程信息
struct threadinfo
{
    std::string _name;
    pthread_t tid;
};

// 设置单例线程池
template<class T>
class threadpool
{


private:
    const static int default_num = 5;

    void lock()
    {
        pthread_mutex_lock(&_lock);
    }
    void unlock()
    {
        pthread_mutex_unlock(&_lock);
    }
    void thread_wake()
    {
        pthread_cond_signal(&_cond, &_lock);
    }
    void thread_push_wake()   // 唤醒生产者
    {
        pthread_cond_signal(*_pcond, &_lock);
    }
    void thread_sleep()
    {
        pthread_cond_wait(&_cond);
    }
    void thread_push_sleep()  // 截停生产者
    {
        pthread_cond_wait(&_pcond, &_lock);
    }
    bool is_threadpool_empty()
    {
        return _threads_task.empty();
    }

public:

    // 线程任务(必为static void*, 否则隐指针this会干扰)
    static void* handler_task(void* args)
    {
        threadpool<T>* tp = static_cast<threadpool<T>*>(args);  // 安全转换

        // 条件暂定
        while (true)
        {
            tp->lock();
            while(tp->is_threadpool_empty())
            {
                tp->thread_sleep();
            }
            T t = tp->pop();
            t();
            tp->thread_push_wake();
            tp->unlock();
        }
    }

    // 多线程创造
    void start()
    {
        if (isopen)  return;

        for (int i = 0; i < _threads_info.size(); i++)
        {
            _threads_info[i].name = "thread-" + std::to_string(i+1);
            pthread_create(_threads_info[i].tid, nullptr, handler_task, this);
            isopen = true;
        }
    }

    void push(const T& t)
    {
        lock();
        while(_threads_task.size() > default_num)
        {
            thread_push_sleep();
        }
        _threads_task.push(t);
        thread_wake();

        unlock();
    }
    T pop()
    {
        T t = _threads_task.front();
        _threads_task.pop();
        return t;
    }


    static threadpool<T>* GetInstance()
    {
        // 防止频繁访问锁
        if (_tp == nullptr)
        {
            pthread_mutex_lock(&_instance_lock);
            // 防止申请多个单例
            if (_tp == nullptr)
            {
                _tp = new threadpool<T> ();
            }
            pthread_mutex_unlock(&_instance_lock);
        }
        return _tp;
    }

private:
    threadpool(int num = default_num)
        : _threads_info(num)
    {
        pthread_mutex_init(&_lock);
        pthread_cond_init(&_cond);
    }
    ~threadpool()
    {
        pthread_mutex_destroy(&_lock);
        pthread_cond_destroy(&_cond);
    }
    threadpool(const threadpool<T>&) = delete;
    const threadpool& operator=(const threadpool<T>&) = delete;


private:

    std::vector<T> _threads_info;   // 线程信息列表 
    std:: queue<T> _threads_task;   // 线程运行队列

    bool isopen = false;
    pthread_mutex_t _lock;          // 锁
    pthread_cond_t  _cond;          // 条件
    pthread_cond_t _pcond;          // push锁条件

    static pthread_mutex_t _instance_lock = PTHREAD_MUTEX_INITIALIZER;  // 用于取单例用的锁
    static threadpool<T>*  _tp = nullptr;                               // 单例指针
};

